package com.ccl.iot.managers;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.ccl.iot.EIOT_RESULT;
import com.ccl.iot.IOTCallback;
import com.ccl.iot.IOTDataType;
import com.ccl.iot.IOTInterface.IOTOnlineMonitorInterface.IOTOnlineStatusChangeListener;
import com.ccl.iot.IOTListScanner;
import com.ccl.iot.IOTNetAPI;
import com.ccl.iot.IOTNetAPIEnum;
import com.ccl.iot.IOTObject.IOTScannableObject;
import com.ccl.iot.bean.CacheDevBean;
import com.ccl.iot.device.Aircondition25IconProvider;
import com.ccl.iot.device.Aircondition8IconProvider;
import com.ccl.iot.device.AircontidionControler;
import com.ccl.iot.device.Batch2IntentionControler;
import com.ccl.iot.device.DimmerControler;
import com.ccl.iot.device.DimmerIconProvider;
import com.ccl.iot.device.DoorControler;
import com.ccl.iot.device.DoorIconProvider;
import com.ccl.iot.device.IOTAirCondition25;
import com.ccl.iot.device.IOTAirCondition8;
import com.ccl.iot.device.IOTBLir;
import com.ccl.iot.device.IOTComplexDevice;
import com.ccl.iot.device.IOTDevice;
import com.ccl.iot.device.IOTDeviceConst;
import com.ccl.iot.device.IOTDimmer;
import com.ccl.iot.device.IOTDoor;
import com.ccl.iot.device.IOTMultiFunc5525;
import com.ccl.iot.device.IOTProbe;
import com.ccl.iot.device.IOTRgbLight;
import com.ccl.iot.device.IOTSecurityArm;
import com.ccl.iot.device.IOTSwitch;
import com.ccl.iot.device.IOTVirtualDevice;
import com.ccl.iot.device.MultiFunc5525Controler;
import com.ccl.iot.device.MultiFunc5525IconProvider;
import com.ccl.iot.device.ProbeControler;
import com.ccl.iot.device.ProbeIconProvider;
import com.ccl.iot.device.RGBLightIconProvider;
import com.ccl.iot.device.RgbLightControler;
import com.ccl.iot.device.SecurityArmIconProvider;
import com.ccl.iot.device.SubBlIrIconProvider;
import com.ccl.iot.device.SwitchControler;
import com.ccl.iot.device.SwitchIconProvider;
import com.ccl.iot.dvr.utils.LogUtil;
import com.ccl.iot.huiju.MainActivity;
import com.ccl.iot.ir.BroadLinkManager;
import com.ccl.iot.object.IOTAuthInfo;
import com.ccl.iot.object.IOTDeviceInfoEx;
import com.ccl.iot.privates.InfoProcessor;
import com.ccl.iot.privates.ListMap;
import com.ccl.iot.privates.RomInfoBean;
import com.ccl.iot.publics.ClassManager;
import com.ccl.iot.publics.Debugger;
import com.ccl.iot.publics.ThreadPoolUtils;
import com.ccl.iot.publics.UIUtils;
import com.ccl.iot.updater.HttpHelper;
import com.google.gson.Gson;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class DeviceManager extends ListedManager<IOTDevice> implements IOTScannableObject<IOTDevice> {
    /*
     * 	Static functions
     */
    private static long gLastDecodeScanTime = 0;

    private static DeviceManager gDefault = null;

    public static DeviceManager GetDefaultManager(Context aContext) {
        if (gDefault == null) {
            gDefault = new DeviceManager(aContext);
        }

        return gDefault;
    }

    public static DeviceManager GetDefaultManager() {
        return gDefault;
    }

    public static class IOTDeviceConstructor {
        private Class<?> iDeviceClass = null;
        private int iAddress = 0;
        private int iSize = 0;

        public IOTDeviceConstructor(Class<?> aDeviceClass, int aAddress, int aSize) {
            iDeviceClass = aDeviceClass;
            iAddress = aAddress;
            iSize = aSize;
        }

        public int getAddress() {
            return iAddress;
        }

        public int getSize() {
            return iSize;
        }

        public Class<?> getDeviceClass() {
            return iDeviceClass;
        }
    }

    public static class IOTDeviceConstructors {
        private int iAddress = 0;
        private int iSize = 0;
        private ArrayList<IOTDeviceConstructor> iConstructors = null;

        public IOTDeviceConstructors(Class<?> aDeviceClass, int aAddress, int aSize) {
            iConstructors = new ArrayList<IOTDeviceConstructor>();

            iConstructors.add(new IOTDeviceConstructor(aDeviceClass, aAddress, aSize));
            iAddress = aAddress;
            iSize = aSize;
        }

        public int getAddress() {
            return iAddress;
        }

        public int getSize() {
            return iSize;
        }

        public boolean append(Class<?> aDeviceClass, int aAddress, int aSize) {
            if (aAddress == iAddress + iSize) {
                iSize += aSize;

                return iConstructors.add(new IOTDeviceConstructor(aDeviceClass, aAddress, aSize));
            }

            return false;
        }

        public int getConstructorCount() {
            if (iConstructors != null) {
                return iConstructors.size();
            }

            return 0;
        }

        public IOTDeviceConstructor getConstructor(int aIndex) {
            if (iConstructors != null) {
                return iConstructors.get(aIndex);
            }

            return null;
        }

        public IOTDeviceConstructor findConstructor(int aAddress, int aSize) {
            if (iConstructors != null) {
                if (aAddress >= iAddress && (aAddress + aSize < iAddress + iSize)) {
                    for (int i = 0, tCount = iConstructors.size(); i < tCount; i++) {
                        IOTDeviceConstructor tConstructor = iConstructors.get(i);

                        if (tConstructor != null && tConstructor.iAddress == aAddress && tConstructor.iSize == aSize) {
                            return tConstructor;
                        }
                    }
                }
            }

            return null;
        }
    }

    private static ListMap<Integer, IOTDeviceConstructors> gDeviceTypes = null;

    public static boolean RegisterDeivceType(Class<?> aDevice, int aType, int aAddress, int aSize) {
        IOTDeviceConstructors tConstructors = null;

        if (gDeviceTypes == null) {
            gDeviceTypes = new ListMap<Integer, IOTDeviceConstructors>();
        } else {
            synchronized (gDeviceTypes) {
                tConstructors = gDeviceTypes.getValue(aType);
            }
        }

        if (tConstructors == null) {
            return gDeviceTypes.add(aType, new IOTDeviceConstructors(aDevice, aAddress, aSize));
        } else {
            return tConstructors.append(aDevice, aAddress, aSize);
        }
    }

    /**
     * 根据类的构造函数构造设备对象
     *
     * @param aDevID
     * @param aDeviceInfo
     * @return
     */
    public static IOTDevice BuildDevice(long aDevID, IOTDeviceInfoEx aDeviceInfo) {
        if (aDevID != 0 && aDeviceInfo != null) {
            if (gDeviceTypes != null) {
                IOTDeviceConstructors tConstructors = gDeviceTypes.getValue(aDeviceInfo.iType);

                if (tConstructors != null) {
                    int tCount = tConstructors.getConstructorCount();

                    if (tCount == 1) {
                        IOTDeviceConstructor tDevConstructor = tConstructors.getConstructor(0);

                        if (tDevConstructor != null) {
                            Constructor<?> tConstructor = ClassManager.FindConstructor(tDevConstructor.getDeviceClass(), aDevID, aDeviceInfo, tDevConstructor.getAddress(), tDevConstructor.getSize());

                            if (tConstructor != null) {
                                try {
                                    return (IOTDevice) tConstructor.newInstance(aDevID, aDeviceInfo, tDevConstructor.getAddress(), tDevConstructor.getSize());
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            } else {
                                Debugger.Error(tDevConstructor.getDeviceClass());
                            }
                        }
                    } else if (tCount > 1) {
                        IOTDevice tDevices[] = new IOTDevice[tCount];
                        for (int i = 0; i < tCount; i++) {
                            IOTDeviceConstructor tDevConstructor = tConstructors.getConstructor(i);

                            if (tDevConstructor != null) {
                                Constructor<?> tConstructor = ClassManager.FindConstructor(tDevConstructor.getDeviceClass(), aDevID, aDeviceInfo, tDevConstructor.iAddress, tDevConstructor.iSize);

                                if (tConstructor != null) {
                                    try {
                                        tDevices[i] = (IOTDevice) tConstructor.newInstance(aDevID, aDeviceInfo, tDevConstructor.iAddress, tDevConstructor.iSize);
                                    } catch (Exception e) {
                                        e.printStackTrace();

                                        return null;
                                    }
                                } else {
                                    Debugger.Error(tDevConstructor.getDeviceClass());
                                }
                            }
                        }

                        return new IOTComplexDevice(aDevID, aDeviceInfo, tConstructors.iAddress, tConstructors.iSize, tDevices);
                    }
                }
            }
        }

        return null;
    }

    public static String Encode(IOTDevice aDevice) {
        if (aDevice != null) {
            return aDevice.getID() + "," + aDevice.getRegisterAddress() + "," + aDevice.getRegisterSize();
        }

        return null;
    }

    public static boolean Decodable(String aDevice) {
        if (aDevice != null) {
            String tInfo[] = aDevice.split(",");

            if (tInfo.length == 3) { // Standard device encode
                try {
                    Long.parseLong(tInfo[0]);
                    Integer.parseInt(tInfo[1]);
                    Integer.parseInt(tInfo[2]);
                } catch (Exception e) {
                    e.printStackTrace();

                    return true;
                }
            } else if (tInfo.length == 1) { // Device id
                try {
                    Long.parseLong(tInfo[0]);

                    return true;
                } catch (Exception e) {
                }
            }
        }

        return false;
    }

    /**
     * 根据设备id获取设备
     *
     * @param aDevID
     * @return
     */
    public static IOTDevice FindDevice(long aDevID) {
        if (gDefault != null) {
            return gDefault.findDevice(aDevID);
        }

        return null;
    }

    public static IOTDevice Decode(long aDevID) {
        if (gDefault != null) {
            IOTDevice tDevice = null;

            tDevice = gDefault.findDevice(aDevID);

            if (tDevice == null) {
                long tTime = System.currentTimeMillis();

                if (tTime - gLastDecodeScanTime > 1000) {
                    gLastDecodeScanTime = tTime;

                    if (gDefault.startScan(null, false)) {
                        tDevice = gDefault.findDevice(aDevID);
                    }
                }
            }

            return tDevice;
        }

        return null;
    }

    public static IOTDevice Decode(String aDevice) {
        if (aDevice != null) {
            String tInfo[] = aDevice.split(",");

            if (tInfo.length == 3) {
                long tID = 0;
                int tAddress = 0;
                int tSize = 0;
                IOTDevice tDevice = null;

                try {
                    tID = Long.valueOf(tInfo[0]);
                    tAddress = Integer.valueOf(tInfo[1]);
                    tSize = Integer.valueOf(tInfo[2]);
                } catch (Exception e) {
                    e.printStackTrace();

                    return null;
                }

                if (gDefault != null) {
                    tDevice = gDefault.findDevice(tID, tAddress, tSize);

                    if (tDevice == null) {
                        if (gDefault.startScan(null, false)) {
                            tDevice = gDefault.findDevice(tID, tAddress, tSize);
                        }
                    }
                }

                return tDevice;
            } else if (tInfo.length == 1) {
                try {
                    return Decode(Long.valueOf(tInfo[0]));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

    /**
     * 分解多路设备
     *
     * @param aDevice
     * @return
     */
    public static ArrayList<IOTDevice> ExplodeDevice(IOTDevice aDevice) {
        if (aDevice != null) {
            ArrayList<IOTDevice> tDevices = new ArrayList<IOTDevice>();

            if (aDevice instanceof IOTComplexDevice) {
                IOTComplexDevice tDevice = (IOTComplexDevice) aDevice;
                int tCount = tDevice.getDeviceCount();

                for (int i = 0; i < tCount; i++) {
                    tDevices.add(tDevice.getDevice(i));
                }
            } else {
                tDevices.add(aDevice);
            }

            return tDevices;
        }

        return null;
    }

    /*
     * 	Non-static functions
     */
    private IOTNetAPI iNetAPI = null;
    private UserManager iUserManager = null;
    private AuthManager iAuthManager = null;
    private RegisterManager iRegManager = null;

    private ArrayList<IOTDevice> iDevices = null;
    private ArrayList<IOTDevice> iOnlineDevices = null;
    private ArrayList<IOTOnlineStatusChangeListener> iOnlineListeners = null;

    private ArrayList<IOTDevice> iOnlineBeforeScan = null;
    private IOTListScanner<IOTDevice> iScanner = new IOTListScanner<IOTDevice>(this);

    private ArrayList<IOTDeviceInfoEx> mDevInfos = null;

    private Object lock = new Object();

    private DeviceManager(Context aContext) {
        super(aContext);
        registerDeviceType();

        registerDeviceIconProvider();
        onCreate();
    }

    /**
     * 注册设备类型
     */
    private void registerDeviceType() {
        // One way switch
        RegisterDeivceType(IOTSwitch.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_ONE_WAY_SWITCH,
                IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_ADDRESS_STATE_1, IOTDeviceConst.TDEVREG_SIZE.EDEVREG_SIZE_STATE);
        // Two way switch
        RegisterDeivceType(IOTSwitch.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_TWO_WAY_SWITCH,
                IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_ADDRESS_STATE_1, IOTDeviceConst.TDEVREG_SIZE.EDEVREG_SIZE_STATE);
        RegisterDeivceType(IOTSwitch.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_TWO_WAY_SWITCH,
                IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_ADDRESS_STATE_2, IOTDeviceConst.TDEVREG_SIZE.EDEVREG_SIZE_STATE);
        // Door
        RegisterDeivceType(IOTDoor.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_ONE_WAY_DOOR,
                IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_ADDRESS_STATE_1, IOTDeviceConst.TDEVREG_SIZE.EDEVREG_SIZE_STATE);
        // Two way dimmer
        RegisterDeivceType(IOTDimmer.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_TWO_WAY_DIMMER,
                IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_DIMMER_ADDRESS_STATE_1, IOTDeviceConst.TDEVREG_SIZE.EDEVREG_DIMMER_SIZE_STATE);
        RegisterDeivceType(IOTDimmer.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_TWO_WAY_DIMMER,
                IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_DIMMER_ADDRESS_STATE_2, IOTDeviceConst.TDEVREG_SIZE.EDEVREG_DIMMER_SIZE_STATE);

        // Multi function 5525
        RegisterDeivceType(IOTMultiFunc5525.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_MULTIFUNC_5525,
                IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_ADDRESS_STATE_FLAG, IOTDeviceConst.TDEVREG_SIZE.EDEVREG_TERMINAL_MULTIFUNC_5525_SIZE);

        // Eight way Air-Condition
        for (int i = 0; i < 8; i++) {
            RegisterDeivceType(IOTAirCondition8.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_AIR_CONDITION_8,
                    IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_ADDRESS_POWER + (IOTDeviceConst.TDEVREG_SIZE.EDEVREG_TERMINAL_AIRCONDITION_SIZE_8 * i), IOTDeviceConst.TDEVREG_SIZE.EDEVREG_TERMINAL_AIRCONDITION_SIZE_8);
        }

        // TwentyFive way Air-Condition
        for (int i = 0; i < 25; i++) {
            RegisterDeivceType(IOTAirCondition25.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_AIR_CONDITION_25,
                    IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_ADDRESS_POWER + (IOTDeviceConst.TDEVREG_SIZE.EDEVREG_TERMINAL_AIRCONDITION_SIZE_25 * i), IOTDeviceConst.TDEVREG_SIZE.EDEVREG_TERMINAL_AIRCONDITION_SIZE_25);
        }

        // Sixteen way probe device
        RegisterDeivceType(IOTProbe.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_ANTI_THEFT_PROBE,
                IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_ADDRESS_POWER, IOTDeviceConst.TDEVREG_SIZE.EDEVREG_TERMINAL_PROBE_SIZE * 16);

        RegisterDeivceType(IOTSecurityArm.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_SECURITY_ARM,
                IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_ADDRESS_POWER, IOTDeviceConst.TDEVREG_SIZE.EDEVREG_TERMINAL_SECURITYARM_SIZE);

        //Rgb Light
        RegisterDeivceType(IOTRgbLight.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_RGB_LIGHT,
                IOTDeviceConst.TDEVREG_ADDRESS.EDEVREG_ADDRESS_STATE_1, IOTDeviceConst.TDEVREG_SIZE.EDEVREG_TERMINAL_RGB_LIGHT_SIZE);

        //BL ir device
        RegisterDeivceType(IOTBLir.class, IOTDeviceConst.TDEVICE_TYPE.EDEVICE_TYPE_TERMINAL_BLIR, 0, 0);

    }

    /**
     * 注册设备图标提供者
     */
    private void registerDeviceIconProvider() {
        SwitchIconProvider.RegisterProviderType();
        DoorIconProvider.RegisterProviderType();
        DimmerIconProvider.RegisterProviderType();
        MultiFunc5525IconProvider.RegisterProviderType();
        Aircondition8IconProvider.RegisterProviderType();
        Aircondition25IconProvider.RegisterProviderType();
        ProbeIconProvider.RegisterProviderType();
        RGBLightIconProvider.RegisterProviderType();
        SecurityArmIconProvider.RegisterProviderType();
        //        BlIrIconProvider.RegisterProviderType();
        SubBlIrIconProvider.RegisterProviderType();

        SwitchControler.RegisterControlerType();
        DoorControler.RegisterControlerType();
        DimmerControler.RegisterControlerType();
        MultiFunc5525Controler.RegisterControlerType();
        AircontidionControler.RegisterControlerType();
        ProbeControler.RegisterControlerType();
        RgbLightControler.RegisterControlerType();
        Batch2IntentionControler.RegisterControlerType();
    }

    @Override
    public boolean filteError(int aError) {
        if (aError == EIOT_RESULT.EIOT_RESULT_GENERAL_NO_ONLINE_DEVICE ||
                aError == EIOT_RESULT.EIOT_RESULT_GENERAL_WRITE_ACCEPTED || aError == EIOT_RESULT.EIOT_RESULT_NO_EFFECT) {
            return true;
        } else if (aError == EIOT_RESULT.EIOT_RESULT_TIMEOUT) {
            return iScanner.isScanning();
        }

        return false;
    }

    private void onCreate() {
        super.create();
        iNetAPI = IOTNetAPI.GetInstance();

        iUserManager = UserManager.GetDefaultManager();
        iAuthManager = AuthManager.GetDefaultManager();

        iUserManager.addUserEventListener(iUserLoginListener);
        iNetAPI.setDeviceInfoCallback(iDeviceInfoCallback);
        iAuthManager.setAuthStateCallback(iAuthStateCallback);
    }

    public void loadCacheDevs() {
        iRegManager = RegisterManager.GetDefaultManager();
        Log.e("loadCacheDevs", "loadCacheDevs iRegManager: "+iRegManager);
        while(iRegManager == null){
            iRegManager = RegisterManager.GetDefaultManager(getContext());
            Log.e("loadCacheDevs", "loadCacheDevs..");
        }

        FileInputStream fis = null;
        File file = new File(InfoProcessor.INFO_PATH + iUserManager.getLogonUser() + "/devcache.json");
        if (file.exists() && file.isFile()) {
            try {
                fis = new FileInputStream(file);
                byte[] buff = new byte[1024 * 10];
                int len;
                StringBuffer sb = new StringBuffer();
                while ((len = fis.read(buff)) > 0) {
                    sb.append(new String(buff, 0, len));
                }
                String infos = sb.toString();
                if (!TextUtils.isEmpty(infos)) {
                    ArrayList arrayList = JSON.parseObject(infos, ArrayList.class);
                    if (arrayList != null && arrayList.size() >= 0) {
                        if (iOnlineDevices == null) {
                            iOnlineDevices = new ArrayList<>();
                        }

                        if (iDevices == null) {
                            iDevices = new ArrayList<>();
                        }
                        for (int i = 0; i < arrayList.size(); i++) {
                            String json = (String) arrayList.get(i);
                            CacheDevBean cacheDevBean = JSON.parseObject(json, CacheDevBean.class);
                            if (findDevice(cacheDevBean.iID) != null) {
                                continue;
                            }
                            if (cacheDevBean != null) {
                                IOTDevice iotDevice = addDevice(cacheDevBean.iID, new IOTDeviceInfoEx(cacheDevBean.iType,
                                        cacheDevBean.iModel, cacheDevBean.iVersion, cacheDevBean.iRegisterSpace));
                                iotDevice.setOnline(cacheDevBean.iOnline);
                                iotDevice.setAuth(cacheDevBean.iAuthState);
                                byte[] data = new byte[cacheDevBean.aData.size()];
                                for (int j = 0; j < data.length; j++) {
                                    data[j] = (byte) ((int) (cacheDevBean.aData.get(j)));
                                }
                                iotDevice.updateRegister(cacheDevBean.iAddress, cacheDevBean.aSize, data, 0, IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_BOTH, 0);
                                iOnlineDevices.add(iotDevice);
                                iDevices.add(iotDevice);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    @Override
    public void onSuspend() {
        super.onSuspend();

        iScanner.reset();
        //        setOnline(iDevices, false);

        if (iOnlineDevices != null && iOnlineDevices.size() > 0) {
            ThreadPoolUtils.getInstance().addTask(new Runnable() {
                @Override
                public void run() {
                    ArrayList<String> devsString = new ArrayList<String>();
                    for (IOTDevice dev : iOnlineDevices) {
                        String saveString = dev.getSaveString();
                        //                        Log.e("getSaveString", "Name: " + dev.getName());
                        //                        Log.e("getSaveString", "String: " + saveString);
                        if (saveString != null) {
                            devsString.add(saveString);
                        }
                    }

                    File rootFile = new File(InfoProcessor.INFO_PATH + iUserManager.getLogonUser());
                    if (!rootFile.exists() || !rootFile.isDirectory()) {
                        rootFile.mkdirs();
                    }

                    String s = JSON.toJSONString(devsString);
                    FileOutputStream fos = null;
                    try {
                        fos = new FileOutputStream(new File(InfoProcessor.INFO_PATH + iUserManager.getLogonUser() + "/devcache.json"));
                        fos.write(s.getBytes());
                        fos.flush();
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (fos != null) {
                            try {
                                fos.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            });
        }
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    public int getDeviceCount() {
        if (iDevices != null) {
            return iDevices.size();
        }

        return 0;
    }

    public int getDeviceCount(boolean aOnlineOnly, int... aAuths) {
        ArrayList<IOTDevice> tList = getList(aOnlineOnly, aAuths);

        if (tList != null) {
            return tList.size();
        }

        return 0;
    }

    public ArrayList<IOTDevice> getList() {
        if (iDevices != null) {
            return new ArrayList<IOTDevice>(iDevices);
        }

        return iDevices;
    }

    public ArrayList<IOTDevice> getList(boolean aOnline) {
        if (aOnline) {
            if (iOnlineDevices != null) {
                return new ArrayList<IOTDevice>(iOnlineDevices);
            }
        } else if (iDevices != null) {
            int tCount = iDevices.size();

            if (tCount > 0) {
                if (iOnlineDevices != null && iOnlineDevices.size() == tCount) {
                    return null;
                } else {
                    ArrayList<IOTDevice> tList = new ArrayList<IOTDevice>();

                    for (int i = 0; i < tCount; i++) {
                        IOTDevice tDevice = iDevices.get(i);

                        if (tDevice != null && tDevice.isOnline() == aOnline) {
                            LogUtil.i(MainActivity.TAG,"Device.getName:" + tDevice.getName());
                            tList.add(tDevice);
                        }
                    }

                    if (tList.size() > 0) {
                        return tList;
                    }
                }
            }
        }

        return null;
    }

    public ArrayList<IOTDevice> getList(boolean aOnlineOnly, int... aAuths) {
        final ArrayList<IOTDevice> tDevices = aOnlineOnly ? iOnlineDevices : iDevices;

        if (tDevices != null && aAuths != null && aAuths.length > 0) {
            ArrayList<IOTDevice> tList = new ArrayList<IOTDevice>();

            for (int i = 0; i < tDevices.size(); i++) {
                IOTDevice tDevice = tDevices.get(i);

                if (tDevice != null && !(tDevice instanceof IOTVirtualDevice)) {
                    for (int j = 0; j < aAuths.length; j++) {
                        if (tDevice.getAuth() == aAuths[j]) {
                            tList.add(tDevice);

                            break;
                        }
                    }
                }
            }

            if (tList.size() > 0) {
                return tList;
            } else {
                return null;
            }
        } else {
            return getList();
        }
    }

    /**
     * 根据设备id获取设备
     *
     * @param aDevID
     * @return
     */
    public IOTDevice findDevice(long aDevID) {
        if (aDevID != 0 && iDevices != null) {
            IOTDevice tDevice;

            for (int i = 0; i < iDevices.size(); i++) {
                if ((tDevice = iDevices.get(i)) != null) {
                    if (tDevice.getID() == aDevID) {
                        return tDevice;
                    }
                }
            }
        }

        return null;
    }

    /**
     * 根据设备id获取设备
     *
     * @param aDevID
     * @return
     */
    public IOTDevice findOrAddDevice(long aDevID) {
        IOTDevice tDevice = findDevice(aDevID);

        if (aDevID != 0 && tDevice == null) {
            return genDevice(aDevID);
        }
        return null;
    }


    /**
     * 根据设备id,设备寄存器地址和寄存器大小获取多路设备中的单个设备
     *
     * @param aDevID   设备id
     * @param aAddress 设备寄存器地址
     * @param aSize    设备寄存器大小
     * @return
     */
    public IOTDevice findDevice(long aDevID, int aAddress, int aSize) {
        IOTDevice tDevice = findDevice(aDevID);

        if (tDevice != null) {
            if (tDevice instanceof IOTComplexDevice) {
                IOTComplexDevice tDevices = (IOTComplexDevice) tDevice;
                int tCount = tDevices.getDeviceCount();

                if (tCount > 0) {
                    for (int i = 0; i < tCount; i++) {
                        if ((tDevice = tDevices.getDevice(i)) != null) {
                            if (tDevice.getRegisterAddress() == aAddress && tDevice.getRegisterSize() == aSize) {
                                return tDevice;
                            }
                        }
                    }
                }
            } else if (tDevice.getRegisterAddress() == aAddress && tDevice.getRegisterSize() == aSize) {
                return tDevice;
            }
        }
        return null;
    }

    /**
     * 添加新上线的设备
     *
     * @param aDevice
     * @return
     */
    public synchronized boolean addDevice(IOTDevice aDevice) {
        if (aDevice != null) {

            if (iDevices == null) {
                iDevices = new ArrayList<IOTDevice>();
            } else if (iDevices.contains(aDevice)) {
                return false;
            }

            if (iDevices.add(aDevice)) {

                // 设置寄存器的操作接口
                aDevice.setRegisterInterface(iRegManager);

                if (iOnlineListeners != null) {
                    IOTOnlineStatusChangeListener tListener;

                    synchronized (iOnlineListeners) {
                        for (int i = 0, tCount = iOnlineListeners.size(); i < tCount; i++) {
                            if ((tListener = iOnlineListeners.get(i)) != null) {
                                aDevice.addOnlineChangeListener(tListener);
                            }
                        }
                    }
                }
            }
        }

        return false;
    }

    /**
     * 添加新上线的设备
     */
    public IOTDevice addDevice(long aDevID, IOTDeviceInfoEx aDeviceInfo) {
        if (aDevID != IOTNetAPI.KINVALID_DEVICE_ID && aDeviceInfo != null) {
            if (findDevice(aDevID) == null) {
                if (aDeviceInfo != null) {

                    if (mDevInfos == null) {
                        mDevInfos = new ArrayList<IOTDeviceInfoEx>();
                    }

                    mDevInfos.add(aDeviceInfo);

                    IOTDevice tDevice = BuildDevice(aDevID, aDeviceInfo);

                    if (tDevice != null) {
                        addDevice(tDevice);

                        super.onNewObject(tDevice);

                        return tDevice;
                    }
                }
            }

        }

        return null;
    }

    /**
     * 手动添加设备, 针对红外设备
     *
     * @return
     */
    public IOTDevice addDevice(IOTDevice iotDevice, long id) {
        if (iotDevice != null && id != IOTNetAPI.KINVALID_DEVICE_ID) {
            if (findDevice(iotDevice.getID()) == null) {

                if (iotDevice != null) {
                    addDevice(iotDevice);
                    if (iOnlineDevices == null) {
                        iOnlineDevices = new ArrayList<>();
                    }
                    if (!iOnlineDevices.contains(iotDevice)) {
                        iOnlineDevices.add(iotDevice);
                    }
                    super.onNewObject(iotDevice);
                    refresh(iotDevice);
                    return iotDevice;
                }
            }

        }

        return null;
    }

    // ==================modify start==============

    /**
     * 删除已发现设备, 主要针对5525设备
     *
     * @param id
     */
    public void removeDevice(long id) {
        IOTDevice dev = findDevice(id);
        if (dev != null) {
            iOnlineDevices.remove(dev);
            iDevices.remove(dev);
        } else {
            if (iOnlineDevices != null && iOnlineDevices.size() > 0) {
                for (int i = 0; i < iOnlineDevices.size(); i++) {
                    if (iOnlineDevices.get(i).getID() == id) {
                        iOnlineDevices.remove(i);
                        break;
                    }
                }
            }

            if (iDevices != null && iDevices.size() > 0) {
                for (int i = 0; i < iDevices.size(); i++) {
                    if (iDevices.get(i).getID() == id) {
                        iDevices.remove(i);
                        break;
                    }
                }
            }
        }
    }

    public void addOnlineDev(IOTDevice dev) {
        if (iOnlineDevices != null && iOnlineDevices.size() > 0) {
            if (!iOnlineDevices.contains(dev)) {
                for (int i = 0; i < iOnlineDevices.size(); i++) {
                    if (iOnlineDevices.get(i).getID() == dev.getID()) {
                        iOnlineDevices.remove(i);
                        break;
                    }
                }
                iOnlineDevices.add(dev);
            }
        }
    }

    // ==================modify end==============

    /**
     * 获取多路设备的所有设备
     *
     * @param aDevID
     * @param aAddress
     * @param aSize
     * @return
     */
    public ArrayList<IOTDevice> findDevices(long aDevID, int aAddress, int aSize) {
        IOTDevice tDevice = findDevice(aDevID);

        if (tDevice != null) {
            ArrayList<IOTDevice> tDevices = new ArrayList<IOTDevice>();

            if (tDevice instanceof IOTComplexDevice) {
                int tCount = ((IOTComplexDevice) tDevice).getDeviceCount();

                if (tCount > 0) {
                    IOTComplexDevice tComplexDevice = (IOTComplexDevice) tDevice;

                    for (int i = 0; i < tCount; i++) {
                        if ((tDevice = tComplexDevice.getDevice(i)) != null) {
                            if (IOTDevice.IsRelativeDevice(tDevice, aAddress, aSize)) {
                                tDevices.add(tDevice);
                            }

                            //安防主机
                            if (tDevice instanceof IOTSecurityArm) {
                                IOTSecurityArm iotSecurityArm = (IOTSecurityArm) tDevice;
                                if (IOTSecurityArm.isRelativeDevice(iotSecurityArm, aAddress, aSize)
                                        && !tDevices.contains(tDevice)) {
                                    tDevices.add(tDevice);
                                }
                            }
                        }
                    }
                }
            } else {
                if (IOTDevice.IsRelativeDevice(tDevice, aAddress, aSize)) {
                    tDevices.add(tDevice);
                }

                //安防主机
                if (tDevice instanceof IOTSecurityArm) {
                    IOTSecurityArm iotSecurityArm = (IOTSecurityArm) tDevice;
                    if (IOTSecurityArm.isRelativeDevice(iotSecurityArm, aAddress, aSize)) {
                        tDevices.add(tDevice);
                    }
                }
            }

            if (tDevices.size() > 0) {
                return tDevices;
            }
        }

        return null;
    }

    public int findDeviceIndex(IOTDevice aDevice) {
        if (iDevices != null) {
            return iDevices.indexOf(aDevice);
        }

        return -1;
    }

    /**
     * 检索设备信息
     *
     * @param aDevID
     * @param aInfo
     * @return
     */
    public IOTDeviceInfoEx retriveDeviceInfo(long aDevID, IOTDeviceInfoEx aInfo) {
        if (aInfo == null) {
            aInfo = new IOTDeviceInfoEx();
        }

        if (iNetAPI.retriveDeviceInfo(aDevID, aInfo)) {
            return aInfo;
        }

        return null;
    }

    /**
     * 添加设备在线状态变化的观察者
     *
     * @param aListener
     * @return
     */
    public boolean addOnlineStatusChangeListener(IOTOnlineStatusChangeListener aListener) {
        if (iOnlineListeners == null) {
            iOnlineListeners = new ArrayList<IOTOnlineStatusChangeListener>();
        } else if (iOnlineListeners.contains(aListener)) {
            return false;
        }

        synchronized (iOnlineListeners) {
            if (iOnlineListeners.add(aListener)) {
                if (iDevices != null) {
                    IOTDevice tDevice;

                    for (int i = 0, tCount = iDevices.size(); i < tCount; i++) {
                        if ((tDevice = iDevices.get(i)) != null) {
                            tDevice.addOnlineChangeListener(aListener);
                        }
                    }
                }

                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * 删除设备在线状态变化的观察者
     *
     * @param aListener
     */
    public boolean removeOnlineStatusChangeListener(IOTOnlineStatusChangeListener aListener) {
        if (iOnlineListeners != null) {
            synchronized (iOnlineListeners) {
                if (iOnlineListeners.remove(aListener)) {
                    if (iDevices != null) {
                        IOTDevice tDevice;

                        for (int i = 0, tCount = iDevices.size(); i < tCount; i++) {
                            if ((tDevice = iDevices.get(i)) != null) {
                                tDevice.removeOnlineChangeListener(aListener);
                            }
                        }
                    }

                    return true;
                }
            }
        }

        return false;
    }

    public synchronized boolean setOnline(IOTDevice aDevice, boolean aOnline) {
        if (aDevice != null && aDevice.isOnline() != aOnline) {
            aDevice.setOnline(aOnline);

            while (true) {
                //                if (iOnlineBeforeScan != null) {
                //                    iOnlineBeforeScan.remove(aDevice);
                //                }
                if (iOnlineDevices == null) {
                    iOnlineDevices = new ArrayList<IOTDevice>();
                } else {
                    synchronized (iOnlineDevices) {
                        if (iOnlineDevices.contains(aDevice)) {
                            if (aOnline) {
                                break;
                            }
                        } else {
                            if (aOnline == false) {
                                break;
                            }
                        }
                    }
                }

                synchronized (iOnlineDevices) {
                    if (aDevice.isOnline()) {
                        if (!iOnlineDevices.contains(aDevice)) {
                            iOnlineDevices.add(aDevice);
                        }
                    } else {
                        iOnlineDevices.remove(aDevice);
                    }
                }

                break;
            }

            return true;
        }

        return false;
    }

    public boolean setOnline(ArrayList<IOTDevice> aDeviceList, boolean aOnline) {
        if (aDeviceList != null) {
            IOTDevice tDevice;
            boolean tOK = true;

            for (int i = aDeviceList.size() - 1; i >= 0; i--) {
                if ((tDevice = aDeviceList.get(i)) != null) {
                    tOK &= setOnline(tDevice, aOnline);
                }
            }

            return tOK;
        }

        return false;
    }

    private UserManager.UserEventListener iUserLoginListener = new UserManager.UserEventListener() {
        @Override
        public void onLoginEvent(boolean aCanceled) {
            if (iNetAPI.isLocalReady() == false && iNetAPI.isRemoteReady() == false) {
                //                setOnline(iDevices, false);
                startScan(null);
            }

            //            iRegManager.setMonitorable(iNetAPI.isRemoteReady());
        }

        @Override
        public void onPrepareLogout() {
        }

        @Override
        public void onLogout(boolean aOK) {
            Log.e("onLogout", "onLogout");
            iDevices.clear();
            iOnlineDevices.clear();
        }
    };

    private IOTDevice genDevice(long aDevID, int aType, int aModel, long aVersion, long aRegisterSpace) {
        IOTDevice tDevice;

        // 把super.onNewObject(tDevice);放到addDevice函数中
        /*if ((tDevice = addDevice(aDevID, new IOTDeviceInfoEx(aType, aModel, aVersion, aRegisterSpace))) != null){
            super.onNewObject(tDevice);
		}*/

        // ================modify start==================
        tDevice = addDevice(aDevID, new IOTDeviceInfoEx(aType, aModel, aVersion, aRegisterSpace));
        // ================modify end==================

        return tDevice;
    }

    private IOTDevice genDevice(long aDevID) {
        IOTDevice tDevice;

        if ((tDevice = findDevice(aDevID)) != null) {
            if (tDevice instanceof IOTComplexDevice) {
                IOTComplexDevice aDevice = (IOTComplexDevice) tDevice;
                int tCount = aDevice.getDeviceCount();

                for (int i = 0; i < tCount; i++) {
                    (aDevice.getDevice(i)).setNetWorkState(IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_REMOTE);
                }
            } else {
                tDevice.setNetWorkState(IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_REMOTE);
            }
            //            tDevice.setUpgradeable(false);

            return tDevice;
        } else {
            IOTDeviceInfoEx tDeviceInfo = new IOTDeviceInfoEx();

            if (retriveDeviceInfo(aDevID, tDeviceInfo) != null) {
                tDevice = genDevice(aDevID, tDeviceInfo.iType, tDeviceInfo.iModel, tDeviceInfo.iVersion, tDeviceInfo.iRegisterSpace);
                if (tDevice != null) {
                    if (tDevice instanceof IOTComplexDevice) {
                        IOTComplexDevice aDevice = (IOTComplexDevice) tDevice;
                        int tCount = aDevice.getDeviceCount();

                        for (int i = 0; i < tCount; i++) {
                            (aDevice.getDevice(i)).setNetWorkState(IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_REMOTE);
                        }
                    } else {
                        tDevice.setNetWorkState(IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_REMOTE);
                    }
                }
                return tDevice;
            } else {
                Debugger.Error("Retrive info failed for device " + aDevID);

                return null;
            }
        }
    }

    /**
     * 搜索本地设备的回调
     */
    private IOTCallback.DeviceInfoCallback iDeviceInfoCallback = new IOTCallback.DeviceInfoCallback() {

        @Override
        public void onDeviceInfoCallback(long aDevID, short aType, short aModel, int aVersion, int aRegisterSpace, int aDeviceIP) {
            if (aDevID != IOTNetAPI.KINVALID_DEVICE_ID) {
                IOTDevice tDevice;
                Log.e("IOTCallback", "ID: " + aDevID + ", aType: " + aType + ", aModel: " + aModel + ", aVersion: " + aVersion + ", aRegisterSpace: " + aRegisterSpace + ", aDeviceIP: " + aDeviceIP);
                if ((tDevice = findDevice(aDevID)) == null) {
                    if ((tDevice = genDevice(aDevID, IOTDataType.CU16(aType), IOTDataType.CU16(aModel), IOTDataType.CU32(aVersion), IOTDataType.CU32(aRegisterSpace))) != null) {
                        setOnline(tDevice, true);
                        ArrayList<IOTDevice> explodeDevice = ExplodeDevice(tDevice);
                        for (IOTDevice iotDevice : explodeDevice) {
                            iotDevice.setNetWorkState(IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_LOCAL);
                            //                            LoggerUtil.e("network","新建1:" + iotDevice.getName());
                        }

                    }
                } else {
                    setOnline(tDevice, true);
                    ArrayList<IOTDevice> explodeDevice = ExplodeDevice(tDevice);
                    for (IOTDevice iotDevice : explodeDevice) {

                        //                        iotDevice.setNetWorkState(IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_LOCAL);

                        if (iotDevice.getNetWorkState() == IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_REMOTE) {
                            //又在远程又在本地
                            iotDevice.setNetWorkState(IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_BOTH);
                        }
                        //                        LoggerUtil.e("network","本来1:" + iotDevice.getName() + "网络状态：" + iotDevice.getNetWorkState());
                    }
                    if (iOnlineBeforeScan != null) {
                        iOnlineBeforeScan.remove(tDevice);
                    }
                }
                if (iAuthManager.isDeviceAuthStateCached(aDevID)) {
                    iAuthStateCallback.onAuthStateCallback(IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_REMOTE, aDevID, iAuthManager.getDeviceAuthState(aDevID, false));
                }else if(iRegManager != null){
                    iRegManager.readRegister(tDevice);
                }
            }
        }
    };

    /*
     * 	Scan device part
     */
    @Override
    public boolean isScanning() {
        return iScanner.isScanning();
    }

    public boolean startScan(final IOTScanListener<IOTDevice> aScanListener, boolean aOnlineOnly) {
        if (isScanning()) {
            return true;
        }
        if (iAuthManager != null && iNetAPI.isUserRecord()) {
            if (iOnlineDevices != null && iOnlineDevices.size() > 0) {
                iOnlineBeforeScan = new ArrayList<IOTDevice>(iOnlineDevices); // 记录之前在线的设备, 当这个集合里的设备没有出现在新搜索到的设备集合中说明已经离线了
            } else {
                iOnlineBeforeScan = null;
            }

            if (iUserManager != null) {
                if (!iUserManager.isLogon()) {
                    if (iNetAPI.isLocalReady()) {
                        // 扫描本地设备
                        iNetAPI.scanDevice();
                    }
                }
            }

            // 只搜索在线的设备
            if (aOnlineOnly) {
                //                final IOTLong tID = new IOTLong();
                //                final IOTLong tDevID = new IOTLong();
                return iScanner.startScan(new IOTListScanner.ScanImpl<IOTDevice>() {
                    @Override
                    public void scanStart() {
                        if (iUserManager != null) {
                            while (iUserManager.isLogining())
                                ;
                        }
                        iNetAPI.threadLock();
                    }

                    private IOTDevice getDevice(long aDevID) {
                        IOTDevice tDevice = genDevice(aDevID);
                        if (tDevice != null) {
                            setOnline(tDevice, true);

                            if (iOnlineBeforeScan != null) {
                                iOnlineBeforeScan.remove(tDevice);
                            }

                        }
                        return tDevice;
                    }

                    @Override
                    public List<IOTDevice> scanDevices() {
                        if (iNetAPI.isRemoteReady()) {
                            ArrayList<Long> onlineDeviceList = iNetAPI.getOnlineDeviceList();
                            if (onlineDeviceList != null && onlineDeviceList.size() > 0) {
                                for (Long devId : onlineDeviceList) {
                                    getDevice(devId);
                                }
                            }
                        }
                        return null;
                    }

                    @Override
                    public void scanDone() {
                        iNetAPI.threadUnlock();
                        //                        if (NetworkMonitor.IsConnectedByMobile() == false) {
                        if (iScanner.isScanning() && iNetAPI.isLocalReady()) {
                            // 扫描本地设备
                            iNetAPI.scanDevice();
                        }
                        //                        }
                        if (iScanner.isScanning()) {

                            iAuthManager.startScanAuthDevices(new IOTScanListener<IOTAuthInfo>() {
                                @Override
                                public void onScanResult(IOTScannableObject<?> aScanner, IOTAuthInfo aObject) {
                                    if (iScanner.isScanning()) {
                                        if (aObject != null) {
                                            // 根据搜索回调给设备分配权限
                                            iAuthStateCallback.onAuthStateCallback(IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_REMOTE, aObject.iAuthObject, aObject.iAuthState);
                                        }
                                    } else {
                                        iAuthManager.stopScanAuthDevices();
                                    }
                                }

                                @Override
                                public void onScanStart(IOTScannableObject<?> aScanner) {
                                }

                                @Override
                                public void onScanStop(IOTScannableObject<?> aScanner) {
                                }
                            });

                        }
                        if (iOnlineBeforeScan != null) {
                            setOnline(iOnlineBeforeScan, false);
                        }
                        BroadLinkManager.GetDefaultManager().startScan();
                        InfoProcessor.getInstance().updataAllInfos();
                        scanDown();
                    }
                }, aScanListener);
            } else {
                // 扫描所有设备
                return iScanner.startScan(new IOTListScanner.ScanImpl<IOTDevice>() {
                    private int iIndex = 0;
                    private ArrayList<IOTDevice> iList = null;

                    @Override
                    public void scanStart() {
                        // 获取所有有权限的设备
                        iAuthManager.startScanAuthDevices(new IOTScanListener<IOTAuthInfo>() {
                            @Override
                            public void onScanResult(IOTScannableObject<?> aScanner, IOTAuthInfo aObject) {
                                if (iScanner.isScanning()) {
                                    if (aObject != null) {
                                        IOTDevice tDevice = genDevice(aObject.iAuthObject);

                                        if (tDevice != null) {
                                            if (iList == null) {
                                                iList = new ArrayList<IOTDevice>();
                                            }

                                            iList.add(tDevice);
                                            iAuthStateCallback.onAuthStateCallback(IOTNetAPIEnum.EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_REMOTE, aObject.iAuthObject, aObject.iAuthState);
                                        }
                                    }
                                } else {
                                    iAuthManager.stopScanAuthDevices();
                                }
                            }

                            @Override
                            public void onScanStart(IOTScannableObject<?> aScanner) {
                            }

                            @Override
                            public void onScanStop(IOTScannableObject<?> aScanner) {
                            }
                        });
                    }

                    @Override
                    public List<IOTDevice> scanDevices() {
                        return null;
                    }

                    private boolean newOnlineDevice(long aID) {
                        for (int i = 0, tCount = iList.size(); i < tCount; i++) {
                            IOTDevice tDevice = iList.get(i);

                            if (tDevice != null && tDevice.getID() == aID) {
                                if (iOnlineBeforeScan != null) {
                                    iOnlineBeforeScan.remove(tDevice);
                                }

                                setOnline(tDevice, true);
                                return true;
                            }
                        }

                        return false;
                    }

                    @Override
                    public void scanDone() {


                        if (iScanner.isScanning() && iList != null) {

                            if (iScanner.isScanning() && iNetAPI.isRemoteReady()) {
                                ArrayList<Long> onlineDeviceList = iNetAPI.getOnlineDeviceList();
                                if (onlineDeviceList != null && onlineDeviceList.size() > 0) {
                                    for (long devId : onlineDeviceList) {
                                        newOnlineDevice(devId);
                                    }
                                }
                            }
                        }

                        if (iScanner.isScanning() && iNetAPI.isLocalReady()) {
                            iNetAPI.scanDevice();
                        }

                        if (iOnlineBeforeScan != null) {
                            setOnline(iOnlineBeforeScan, false);
                        }

                        InfoProcessor.getInstance().updataAllInfos();
                        if (aScanListener != null) {
                            aScanListener.onScanStop(null);
                        }
                        scanDown();
                    }
                }, aScanListener);
            }
        } else {
            if (mListener != null) {
                mListener.onScanDone();
            }

        }

        return false;
    }

    @Override
    public boolean startScan(IOTScanListener<IOTDevice> aScanListener) {
        return startScan(aScanListener, true);
    }

    @Override
    public boolean stopScan() {
        return iScanner.stopScan();
    }



    private IOTCallback.AuthStateCallback iAuthStateCallback = new IOTCallback.AuthStateCallback() {
        @Override
        public void onAuthStateCallback(int aNetWork, long aDevID, int aNewAuth) {
            IOTDevice tDevice;

            if ((tDevice = findDevice(aDevID)) != null) {
                if (tDevice.setAuthState(aNetWork, aNewAuth)) {
                    if (tDevice.isReadable()) {
                        iRegManager.readRegister(tDevice.getID(), tDevice.getRegisterAddress(), tDevice.getRegisterSize());
                    }


                } else {
                    if (tDevice.isReadable()) {
                        iRegManager.readRegister(tDevice.getID(), tDevice.getRegisterAddress(), tDevice.getRegisterSize());
                    }

                }

            }
        }
    };

    // ====================modify start=============================
    public ArrayList<IOTDeviceInfoEx> getAllDevInfo() {
        return mDevInfos;
    }

    /**
     * 获取当前所有有权限的设备的型号
     *
     * @return
     */
    public HashSet<Integer> getAllModels() {
        HashSet<Integer> models = null;
        if (mDevInfos != null) {
            models = new HashSet<Integer>();
            for (IOTDeviceInfoEx info : mDevInfos) {
                models.add(info.iModel);
            }
        }
        return models;
    }

    /**
     * 获取指定设备集合的型号
     *
     * @param devices 需要获取型号的设备
     * @return
     */
    public HashSet<Integer> getModels(ArrayList<IOTDevice> devices) {
        HashSet<Integer> models = null;
        if (devices != null) {
            models = new HashSet<Integer>();
            for (IOTDevice dev : devices) {
                models.add(dev.getDeviceInfo().iModel);
            }
        }
        return models;
    }

    /**
     * 根据设备型号进行分类
     *
     * @param devices 需要分类的设备
     * @return
     */
    public ArrayList<Map.Entry<Integer, ArrayList<IOTDevice>>> devCateGory(ArrayList<IOTDevice> devices) {

        HashSet<Integer> models = getModels(devices);
        TreeMap<Integer, ArrayList<IOTDevice>> cateGoryDev = null;
        if (models != null && devices != null) {
            cateGoryDev = new TreeMap<Integer, ArrayList<IOTDevice>>();
            for (Integer integer : models) {
                ArrayList<IOTDevice> devs = new ArrayList<IOTDevice>();
                Iterator<IOTDevice> iterator = devices.iterator();
                while (iterator.hasNext()) {
                    IOTDevice next = iterator.next();
                    if (next.getDeviceInfo().iModel == integer) {
                        if (next.isUpgradeable()) {
                            devs.add(0, next);
                        } else {
                            devs.add(next);
                        }
                        iterator.remove();
                    }
                }
                cateGoryDev.put(integer, devs);
            }
        }

        ArrayList<Map.Entry<Integer, ArrayList<IOTDevice>>> entryArr = new ArrayList<Map.Entry<Integer, ArrayList<IOTDevice>>>(cateGoryDev.entrySet());
        Collections.sort(entryArr, new Comparator<Map.Entry<Integer, ArrayList<IOTDevice>>>() {

            @Override
            public int compare(Map.Entry<Integer, ArrayList<IOTDevice>> list1, Map.Entry<Integer, ArrayList<IOTDevice>> list2) {
                if (list1 != null && list2 != null) {
                    ArrayList<IOTDevice> devs1 = list1.getValue();
                    ArrayList<IOTDevice> devs2 = list2.getValue();
                    if (devs1 != null && devs2 != null && devs1.size() > 0 && devs2.size() > 0) {
                        IOTDevice dev1 = devs1.get(0);
                        IOTDevice dev2 = devs2.get(0);
                        if (dev1.isUpgradeable()) {
                            return -1;
                        } else if (dev2.isUpgradeable()) {
                            return 1;
                        }
                    }
                }
                return 0;
            }
        });

        ArrayList<Map.Entry<Integer, ArrayList<IOTDevice>>> sortArr = new ArrayList<Map.Entry<Integer, ArrayList<IOTDevice>>>();
        Iterator<Entry<Integer, ArrayList<IOTDevice>>> iterator = entryArr.iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, ArrayList<IOTDevice>> entry = iterator.next();
            sortArr.add(entry);
        }
        return sortArr;
    }

    /**
     * 扫描设备完成后的动作
     */
    public void scanDown() {
        // 结束下拉刷新
        if (mListener != null) {
            mListener.onScanDone();
        }
        synchronized (lock) {
            if (mCheckable) {
                mCheckable = false;
                // 检查设备的固件是否可以升级
                checkRomUpdate();
            }
        }
        refresh(null);

    }

    private HashMap<Integer, RomInfoBean> mRomInfos = null;
    private HashMap<Long, String> callbackInfos = null;
    private ArrayList<IOTDevice> mOwnDevice = null;

    public HashMap<Integer, RomInfoBean> getRomInfos() {
        return mRomInfos;
    }

    public HashMap<Long, String> getCallbackInfos() {
        return callbackInfos;
    }


    /**
     * 检查设备固件升级
     */
    private void checkRomUpdate() {
        // if(mRomInfos == null){
        mRomInfos = new HashMap<Integer, RomInfoBean>();
        // }

        // 只有拥有者才能升级
        mOwnDevice = getList(true, IOTNetAPIEnum.EAUTH_STATE.EAUTH_STATE_OWNER);
        if (mOwnDevice != null) {
            ThreadPoolUtils.getInstance().addTask(new Runnable() {
                @Override
                public void run() {

                    for (IOTDevice dev : mOwnDevice) {
                        if (dev != null) {
                            dev.setReupgradeable(false);
                            dev.setUpgradeable(false);
                        }
                    }

                    for (IOTDevice dev : mOwnDevice) {
                        if (dev != null) {
                            IOTDeviceInfoEx info = dev.getDeviceInfo();
                            RomInfoBean romInfoBean = mRomInfos.get(info.iModel);
                            if (romInfoBean == null) {
                                String mModel = GetModel(info.iModel, true);
                                // 获取设备固件信息
                                String path = "http://iot.cclcp.com:5499/Downloads/Firmware/CCL" + mModel + "/firmware.json";
                                final String json = HttpHelper.GetHttpRequestString(path);
                                if (!TextUtils.isEmpty(json)) {
                                    romInfoBean = handlerJson(json, info.iModel, romInfoBean);
                                    scanRomDevice(dev, romInfoBean);
                                }
                            }
                        }
                    }
                }
            });
        }
    }

    public static String GetModel(int model, boolean lower) {
        if (model == 55132) {
            return lower ? "55d1" : "55D1";
        } else if (model == 55121) {
            return lower ? "55c1" : "55C1";
        } else {
            return model + "";
        }
    }

    private void scanRomDevice(final IOTDevice dev, final RomInfoBean infoBean) {
        IOTDeviceInfoEx devInfo = dev.getDeviceInfo();
        if (devInfo != null && infoBean != null) {
            if (callbackInfos == null) {
                callbackInfos = new HashMap<Long, String>();
            } else {
                callbackInfos.clear();
            }
            // 开始扫描固件升级
            boolean upgrade = iNetAPI.upgradeScan((short) devInfo.iType, (short) devInfo.iModel, infoBean.Code, new IOTCallback.UpgradeDeviceInfoCallback() {

                @Override
                public void onUpgradeDeviceInfoCallback(long aDevID, int aDevIP, short aDevicePort) {

                    callbackInfos.put(aDevID, aDevIP + "#" + aDevicePort);

                    if (mOwnDevice != null) {

                        for (IOTDevice dev : mOwnDevice) {
                            if (dev.getID() == aDevID) {
                                Log.e("upgrade", "Name: " + dev.getName());
                                dev.setReupgradeable(true);
                                // 记录回调的信息, 设备的ip和端口
                                dev.setRomUpgradeInfo(aDevIP + "#" + aDevicePort);
                                dev.setUpgradeable(true);
                            }
                        }
                    }

                }
            });
            Log.e("upgrade", "result: " + upgrade + ", devInfo.iType: " + devInfo.iType + ", devInfo.iModel: " + devInfo.iModel + ", infoBean.Code: " + infoBean.Code);

            // 扫描可重新升级的设备(理论上只要是本地的设备就可以重新升级, 但是需要得到设备的ip和端口, 所以只能手动将设备固件的版本提高再搜索一次)
            boolean b = iNetAPI.upgradeScan((short) devInfo.iType, (short) devInfo.iModel, infoBean.Code + 3, new IOTCallback.UpgradeDeviceInfoCallback() {

                @Override
                public void onUpgradeDeviceInfoCallback(long aDevID, int aDevIP, short aDevicePort) {
                    // if (callbackInfos == null) {
                    // callbackInfos = new HashMap<Long, String>();
                    // }
                    // callbackInfos.put(aDevID, aDevIP + "#" + aDevicePort);

                    Log.e("upgrade", "Reupgrade ID: " + aDevID);
                    if (mOwnDevice != null) {
                        for (IOTDevice dev : mOwnDevice) {
                            if (dev.getID() == aDevID) {
                                Log.e("upgrade", "Reupgrade Name: " + dev.getName());
                                dev.setReupgradeable(true);
                                dev.setRomUpgradeInfo(aDevIP + "#" + aDevicePort);
                            }
                        }
                    }
                }
            });
            Log.e("reupgrade", "--result: " + b + ", devInfo.iType: " + devInfo.iType + ", devInfo.iModel: " + devInfo.iModel + ", infoBean.Code: " + infoBean.Code);
        }
    }

    /**
     * 处理固件信息
     *
     * @param json        json信息
     * @param model       设备型号
     * @param romInfoBean
     * @return
     */
    private RomInfoBean handlerJson(String json, int model, RomInfoBean romInfoBean) {
        try {
            Gson gson = new Gson();
            romInfoBean = gson.fromJson(json, RomInfoBean.class);
            mRomInfos.put(model, romInfoBean);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return romInfoBean;
    }


    public void refresh(final IOTDevice newDev) {
        //        LoggerUtil.e("notifyDataSetChanged", "notifyDataSetChanged");
        UIUtils.postTaskSafely(new Runnable() {
            @Override
            public void run() {
                for (OnScanDoneRefresh listener : mScanDoneArr) {
                    listener.onRefresh(newDev);
                }
            }
        });
    }

    private ArrayList<OnScanDoneRefresh> mScanDoneArr = new ArrayList<DeviceManager.OnScanDoneRefresh>();

    public void addScanDoneRefreshListener(OnScanDoneRefresh listener) {
        if (!mScanDoneArr.contains(listener)) {
            //            LoggerUtil.e("添加addScanDoneRefreshListener：");
            mScanDoneArr.add(listener);
        }
    }

    public void removeScanDoneRefreshListener(OnScanDoneRefresh listener) {
        if (mScanDoneArr.contains(listener)) {
            mScanDoneArr.remove(listener);
        }
    }

    public interface OnScanDoneRefresh {
        public void onRefresh(IOTDevice newDev);
    }

    public interface OnScanDoneListener {
        public void onScanDone();
    }

    private OnScanDoneListener mListener;
    private boolean mCheckable = false;

    public void setOnScanDoneListener(OnScanDoneListener listener) {
        mListener = listener;
    }

    public void setCheckRomUpgrade(boolean heckable) {
        mCheckable = heckable;
    }

    // ====================modify end=============================

}
